import { config } from './config.js';

/**
 * Memory initialization utility for Node.js process optimization
 * This should be called as early as possible in the application startup
 */
export class MemoryManager {
  private static initialized = false;

  /**
   * Initialize memory settings based on configuration
   * Note: NODE_OPTIONS must be set before Node.js process starts,
   * so this function will warn if settings cannot be applied dynamically
   */
  static initialize(): void {
    if (this.initialized) {
      return;
    }

    console.error('[MemoryManager] 初始化内存配置...');
    
    const memoryConfig = config.server.memory;
    
    // Print current memory configuration
    console.error(`[MemoryManager] 内存限制: ${memoryConfig.maxOldSpaceSize}MB`);
    console.error(`[MemoryManager] GC启用: ${memoryConfig.enableGC ? '是' : '否'}`);
    console.error(`[MemoryManager] 自动优化: ${memoryConfig.autoOptimizeForLargeRepository ? '是' : '否'}`);
    
    // Check if NODE_OPTIONS is properly set
    const nodeOptions = process.env.NODE_OPTIONS || '';
    const hasMaxOldSpaceSize = nodeOptions.includes('--max-old-space-size');
    const hasExposeGC = nodeOptions.includes('--expose-gc');
    
    if (!hasMaxOldSpaceSize) {
      console.warn(`[MemoryManager] ⚠️  NODE_OPTIONS未设置内存限制`);
      console.warn(`[MemoryManager] 💡 建议设置: NODE_OPTIONS="--max-old-space-size=${memoryConfig.maxOldSpaceSize}"`);
    } else {
      console.error(`[MemoryManager] ✅ NODE_OPTIONS内存限制已设置`);
    }
    
    if (memoryConfig.enableGC && !hasExposeGC) {
      console.warn(`[MemoryManager] ⚠️  NODE_OPTIONS未启用GC接口`);
      console.warn(`[MemoryManager] 💡 建议添加: --expose-gc`);
    } else if (memoryConfig.enableGC) {
      console.error(`[MemoryManager] ✅ GC接口已启用`);
    }
    
    // Auto-optimize for large repositories
    if (memoryConfig.autoOptimizeForLargeRepository) {
      this.setupAutoOptimization();
    }
    
    this.initialized = true;
    console.error('[MemoryManager] 内存配置初始化完成');
  }

  /**
   * Setup automatic memory optimization for large repositories
   */
  private static setupAutoOptimization(): void {
    console.error('[MemoryManager] 设置大型仓库自动内存优化...');
    
    // Force garbage collection periodically if available
    if (global.gc && config.server.memory.enableGC) {
      console.error('[MemoryManager] 启用定期垃圾回收 (每60秒)');
      setInterval(() => {
        const before = process.memoryUsage();
        global.gc!();
        const after = process.memoryUsage();
        
        const freedMB = Math.round((before.heapUsed - after.heapUsed) / 1024 / 1024);
        if (freedMB > 10) { // Only log if significant memory was freed
          console.error(`[MemoryManager] GC释放内存: ${freedMB}MB`);
        }
      }, 60000); // Every 60 seconds
    }
    
    // Monitor memory usage and warn on high usage
    setInterval(() => {
      const usage = process.memoryUsage();
      const heapUsedMB = Math.round(usage.heapUsed / 1024 / 1024);
      const maxMemoryMB = config.server.memory.maxOldSpaceSize;
      const usagePercent = Math.round((heapUsedMB / maxMemoryMB) * 100);
      
      if (usagePercent > 80) {
        console.warn(`[MemoryManager] ⚠️  内存使用率高: ${usagePercent}% (${heapUsedMB}MB/${maxMemoryMB}MB)`);
        
        // Force GC if available and usage is very high
        if (global.gc && usagePercent > 90) {
          console.warn(`[MemoryManager] 🔄 强制执行垃圾回收...`);
          global.gc();
        }
      } else if (usagePercent > 60) {
        console.error(`[MemoryManager] 📊 内存使用: ${usagePercent}% (${heapUsedMB}MB/${maxMemoryMB}MB)`);
      }
    }, 30000); // Every 30 seconds
  }

  /**
   * Get recommended NODE_OPTIONS for current configuration
   */
  static getRecommendedNodeOptions(): string {
    const memoryConfig = config.server.memory;
    const options = [`--max-old-space-size=${memoryConfig.maxOldSpaceSize}`];
    
    if (memoryConfig.enableGC) {
      options.push('--expose-gc');
    }
    
    // Note: --optimize-for-size is not allowed in NODE_OPTIONS
    // Additional optimizations would need to be applied differently
    
    return options.join(' ');
  }

  /**
   * Check if current process has proper memory configuration
   */
  static validateMemoryConfiguration(): boolean {
    const nodeOptions = process.env.NODE_OPTIONS || '';
    const memoryConfig = config.server.memory;
    
    const hasMaxOldSpaceSize = nodeOptions.includes('--max-old-space-size');
    const hasExposeGC = memoryConfig.enableGC ? nodeOptions.includes('--expose-gc') : true;
    
    return hasMaxOldSpaceSize && hasExposeGC;
  }

  /**
   * Get current memory usage statistics
   */
  static getMemoryStats(): {
    heapUsed: number;
    heapTotal: number;
    external: number;
    rss: number;
    heapUsedMB: number;
    heapTotalMB: number;
    externalMB: number;
    rssMB: number;
    usagePercent: number;
    maxConfiguredMB: number;
  } {
    const usage = process.memoryUsage();
    const maxConfiguredMB = config.server.memory.maxOldSpaceSize;
    
    return {
      heapUsed: usage.heapUsed,
      heapTotal: usage.heapTotal,
      external: usage.external,
      rss: usage.rss,
      heapUsedMB: Math.round(usage.heapUsed / 1024 / 1024),
      heapTotalMB: Math.round(usage.heapTotal / 1024 / 1024),
      externalMB: Math.round(usage.external / 1024 / 1024),
      rssMB: Math.round(usage.rss / 1024 / 1024),
      usagePercent: Math.round((usage.heapUsed / 1024 / 1024 / maxConfiguredMB) * 100),
      maxConfiguredMB
    };
  }

  /**
   * Force garbage collection if available
   */
  static forceGC(): boolean {
    if (global.gc && config.server.memory.enableGC) {
      const before = process.memoryUsage();
      global.gc();
      const after = process.memoryUsage();
      
      const freedMB = Math.round((before.heapUsed - after.heapUsed) / 1024 / 1024);
      console.error(`[MemoryManager] 手动GC释放内存: ${freedMB}MB`);
      return true;
    }
    
    console.warn('[MemoryManager] GC不可用，请确保NODE_OPTIONS包含--expose-gc');
    return false;
  }
}